package com.xinchuang.service.targetSystem.Impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xinchuang.entity.target.TargetBaseData;
import com.xinchuang.entity.targetSystem.ExecutableState;
import com.xinchuang.entity.targetSystem.system.SystemEmulateData;
import com.xinchuang.entity.targetSystem.system.SystemsElse;
import com.xinchuang.entity.targetSystem.system.SystemsRange;
import com.xinchuang.entity.targetSystem.target.SystemIndex;
import com.xinchuang.entity.targetSystem.target.SystemIndexElse;
import com.xinchuang.entity.targetSystem.target.TargetSubRelationTable;
import com.xinchuang.mapper.targetSystem.SystemsMasterMapper;
import com.xinchuang.mapper.targetSystem.target.SystemIndexMapper;
import com.xinchuang.mapper.targetSystem.target.SystemsRangeMapper;
import com.xinchuang.service.RedisUseService;
import com.xinchuang.service.target.TargetBaseDataService;
import com.xinchuang.service.targetSystem.AsyncService;
import com.xinchuang.service.targetSystem.ExecutableStateService;
import com.xinchuang.service.targetSystem.Impl.target.SystemIndexServiceImpl;
import com.xinchuang.service.targetSystem.SystemEmulateDataService;
import com.xinchuang.service.targetSystem.indexUtil.IndexComputeService;
import com.xinchuang.service.targetSystem.target.SystemIndexService;
import com.xinchuang.service.targetSystem.target.SystemsElseService;
import com.xinchuang.service.targetSystem.target.TargetSubRelationTableService;
import com.xinchuang.util.FileElseUtil;
import com.xinchuang.util.RedisUtil;
import com.xinchuang.util.SnowflakeIdWorker;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * TODO
 *
 * @author zkwczx
 * @version 1.0
 * @date 2024/4/20 11:54
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AsyncServiceImpl implements AsyncService {

    private SnowflakeIdWorker snow = new SnowflakeIdWorker(0, 0);

    private final SystemIndexService systemIndexService;

    private final TargetBaseDataService targetBaseDataService;

    private final ExecutableStateService executableStateService;

    private final SystemsMasterMapper systemsMasterMapper;

    private final SystemsElseService systemsElseService;

    private final SystemsRangeMapper systemsRangeMapper;

    private final RedisUtil redisUtil;

    private final RedisUseService redisUseService;

    private final IndexComputeService indexComputeService;

    private final SystemIndexMapper systemIndexMapper;

    private final TargetSubRelationTableService targetSubRelationTableService;

    private final SystemEmulateDataService systemEmulateDataService;

    @Async
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createIndexInit(String name, String typeId, String targetId) {
        try {
            Thread.sleep(1000 * 2);
        } catch (Exception e) {

        }
        List<SystemIndex> indexList = systemIndexService.lambdaQuery()
                .eq(SystemIndex::getRedId, typeId)
                .orderByAsc(SystemIndex::getCreateTime)
                .list();
        if (CollectionUtil.isNotEmpty(indexList)) {
            Map<String, String> map = new HashMap<>();
            for (SystemIndex systemIndex : indexList) {
                systemIndex.setRedId(targetId);
                if (systemIndex.getParentId().equals("0")) {
                    systemIndex.setIndicatorName(name);
                } else {
                    map.put(systemIndex.getParentId(), snow.nextId() + "");
                }
            }
            for (SystemIndex systemIndex : indexList) {
                if (null == map.get(systemIndex.getId())) {
                    String id = snow.nextId() + "";
                    systemIndex.setId(id);
                } else {
                    systemIndex.setId(map.get(systemIndex.getId()));
                }
                if (!systemIndex.getParentId().equals("0") && null != map.get(systemIndex.getParentId())) {
                    systemIndex.setParentId(map.get(systemIndex.getParentId()));
                }
                computeLastValue(systemIndex);
            }
            systemIndexService.saveBatch(indexList);
            //计算底层指标
            List<SystemIndex> under = systemIndexService.lambdaQuery()
                    .eq(SystemIndex::getRedId, targetId)
                    .eq(SystemIndex::getType, "under")
                    .isNotNull(SystemIndex::getMsgType)
                    .list();
            if (CollectionUtil.isNotEmpty(under)) {
                for (SystemIndex index : under) {
                    computeUnderIndex(index);
                }
            }
        } else {
            SystemIndex build = SystemIndex.builder().redId(targetId).parentId("0").indicatorValue("0").indicatorName(name).weight("0").weightType("0").level("0").build();
            systemIndexService.save(build);
        }
        executableStateService.saveOrUpdate(ExecutableState.builder().id(targetId).state(2).build());
        log.info(targetId + ":指标数据计算完成");
    }

    private void computeUnderIndex(SystemIndex systemIndex) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("pullValue", systemIndex.getMsgType());
        jsonObject.put("indexValue", JSONObject.parseObject(systemIndex.getIndexMsg()));
        if (indexComputeService.enterCompute(systemIndex, jsonObject)) {
            if (FileElseUtil.getObjectToDouble(systemIndex.getIndicatorValue()) > 0) {
                computeParentValue(
                        systemIndex.getParentId(),
                        FileElseUtil.getObjectToDouble(systemIndex.getWeight()) * FileElseUtil.getObjectToDouble(systemIndex.getIndicatorValue())
                );
            }
        }
        systemIndexService.updateById(systemIndex);
    }

    private void computeParentValue(String parentId, double addValue) {
        SystemIndex systemIndex = systemIndexService.getById(parentId);
        if (ObjectUtil.isNotNull(systemIndex)) {
            double parentAddValue = addValue * FileElseUtil.getObjectToDouble(systemIndex.getWeight());
            systemIndex.setIndicatorValue((FileElseUtil.getObjectToDouble(systemIndex.getIndicatorValue()) + addValue) + "");
            systemIndexService.updateById(systemIndex);
            computeLastValue(systemIndex);
            computeParentValue(systemIndex.getParentId(), parentAddValue);
        }
    }

    @Async
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteSystemsAllBySysId(String sysId) {
        //缓存类型选择列表key
        String typeKey = "systems_target_type_" + sysId;
        //缓存目标列表
        String targetKey = "systemList" + sysId;
        //缓存已选独立目标列表
        String onKey = "systemTargetList" + sysId;
        redisUtil.del(typeKey, targetKey, onKey);
        //删除系统关联统计属性
        systemsMasterMapper.deleteInfo(sysId);
        //删除体系关系
        systemsMasterMapper.deleteShip(sysId);
        //删除体系列表
        systemsMasterMapper.delSystemsElseData(sysId);
        //删除体系关联目标
        systemsMasterMapper.deleteRelation(sysId);
        //删除体系放入目标与类型
        systemsElseService.lambdaUpdate().eq(SystemsElse::getSysId, sysId).remove();
        //删除体系内目标范围
        systemsRangeMapper.delete(new LambdaQueryWrapper<SystemsRange>().eq(SystemsRange::getSysId, sysId));
        //仿真数据删除
        systemEmulateDataService.lambdaUpdate().eq(SystemEmulateData::getSysId, sysId).remove();
        //删除目标列表缓存
        redisUseService.deleteSystemsTargetList(sysId);
        //删除体系关联态势
        redisUseService.deletePosture(sysId, null, true);
        //删除体系目标关联作用缓存
        redisUseService.deleteSystemsRelationRangeValue(sysId, null, true);
    }

    private void computeLastValue(SystemIndex systemIndex) {
        if ("1".equals(systemIndex.getLevel())) {
            if (redisUseService.isTarget(systemIndex.getRedId()) || redisUseService.isSub(systemIndex.getRedId())) {
                redisUseService.addIndexLevelValue(systemIndex.getRedId(), systemIndex.getLevel(), systemIndex.getIndicatorName(), FileElseUtil.getObjectToDouble(systemIndex.getIndicatorValue()));
            }
        }
        if ("0".equals(systemIndex.getParentId())) {
            if (redisUseService.isTarget(systemIndex.getRedId())) {
                targetBaseDataService.lambdaUpdate()
                        .set(TargetBaseData::getIndexValue, FileElseUtil.getObjectToDouble(systemIndex.getIndicatorValue()))
                        .eq(TargetBaseData::getTargetId, systemIndex.getRedId())
                        .update();
            } else if (redisUseService.isSub(systemIndex.getRedId())){
                targetSubRelationTableService.lambdaUpdate()
                        .set(TargetSubRelationTable::getIndexValue, FileElseUtil.getObjectToDouble(systemIndex.getIndicatorValue()))
                        .eq(TargetSubRelationTable::getSubId, systemIndex.getRedId())
                        .update();
            }
        }
    }

}
